优化移动端游戏性能 | 来自Unity顶级工程师的图形与资源相关建议
上一篇,我们分享了 Unity Accelerate Solution 团队对性能分析、内存优化和代码架构的优化建议(点击回看)。本次,这支 Unity 最为资深的软件工程师团队将着重介绍怎样提高资源、项目配置和图形的性能。
本系列共有三篇,另外两篇分别介绍了性能分析、内存和代码架构的优化,及物理模拟、UI 和音频的优化,完整教程已搬运至 Unity 中文课堂,欢迎点击“阅读原文”查看:
https://learn.u3d.cn/tutorial/mobile-game-optimization
项目配置
有几个特定的项目设置会影响移动端游戏的性能。
降低或禁用 Accelerometer Frequency(加速度计频率)
Unity 每秒钟会以一定次数统计移动设备的加速度计状态。如果应用并不会用到加速度计,我们完全可以禁用该功能或降低统计频率来获得更好的性能。
请在游戏不使用加速度计时禁用 Accelerometer Frequency
禁用不必要的 Player 或 Quality 设置
在 Player 设置中,对不支持的平台禁用 Auto Graphics API,以便防止生成过多着色器变体。如果应用程序不支持,对较旧的 CPU 禁用 Target Architectures。
在 Quality 设置中,禁用不需要的质量级别。
禁用不必要的物理设置
如果游戏不使用物理设置,请取消选中 Auto Simulation 和 Auto Sync Transforms。否则它们会降低应用程序运行速度,却并无任何可见的好处。
选择正确的帧率
移动端项目必须在帧率和电池续航时间以及热节流之间获得平衡。不需要将设备限值推向 60 fps,可以折衷以 30 fps 运行。Unity 默认移动端为 30 fps。
您也可以通过 Application.targetFrameRate 在运行时动态调整帧率。例如,您甚至可以将缓慢或相对静止的场景降至 30 fps 以下,而将玩游戏时的 fps 设置保留为较高值。
避免使用过多层级
拆分层级!在层级视图中如果游戏对象不需要嵌套,请简化父子化。较少的层级关系将受益于多线程刷新场景中的变换 (Transform)。复杂层级关系会发生不必要的变换 (Transform) 计算以及更多垃圾收集开销。
请参阅优化层级关系(点击回看)和此 Unite 报告了解变换 (Transform) 的最佳实践。
Unite 报告:
https://www.youtube.com/watch?v=W45-fsnPhJY&t=794s
变换一次,而非两次
另外,移动变换 (Transform) 时,使用 Transform.SetPositionAndRotation 可以一次就同时更新位置和旋转。这样可以避免两次修改变换(Transform)的开销。
Transform.SetPositionAndRotation:
https://docs.unity3d.com/ScriptReference/Transform.SetPositionAndRotation.html
如果需要在运行时初始化游戏对象,一项简单的优化是在初始化过程中父子化和重新定位:
初始化游戏对象:
GameObject.Instantiate(prefab, parent);
GameObject.Instantiate(prefab, parent, position, rotation);
有关 Object.Instantiate 的更多详细信息,请参阅脚本 API。
脚本 API:
https://docs.unity3d.com/ScriptReference/Object.Instantiate.html
假设 Vsync 已启用
移动平台不渲染半帧。即使在编辑器中禁用 Vsync (Project Settings > Quality), Vsync 在硬件级别也处于启用状态。如果 GPU 无法足够快地刷新,将保持当前帧,从而有效降低每秒帧数。
资源
资源管线可以大幅影响应用程序的性能。经验丰富的技术美术师可以帮助您的团队定义和增强资源格式、规范以及导入设置。
不要依赖于默认设置。使用平台特定的覆盖选项卡可以优化纹理和网格几何体等资源。如果设置不正确,则可能造成较大的编译版本大小、较长的构建时间,以及较差的内存使用量。可以考虑使用预设功能来帮助为特定项目自定义基准设置,以确保最优设置。
请参阅此艺术资源最佳实践指南了解更多详细信息,或者在 Unity Learn 上了解有关适用于移动应用程序的 3D 美术优化的课程。
艺术资源最佳实践指南:
Unity Learn 上的课程:
正确导入纹理
纹理会占用大部分内存,因此,导入设置非常重要。通常,请遵循以下指导原则 :
Unity 精灵图集:
https://docs.unity3d.com/cn/current/Manual/class-SpriteAtlas.html
Texture Packer:
https://www.codeandweb.com/texturepacker
压缩纹理
考虑以下使用相同模型和纹理的两个实例。左侧的设置几乎使用右侧设置八倍的内存量,但并没有改善视觉质量。
未压缩的纹理需要更多内存
对 iOS 和 Android 都使用自适应可伸缩纹理压缩 (ATSC)。绝大多数开发目标最低规格设备游戏都支持 ATSC 压缩。
唯一的例外是 :
如果压缩格式(如 PVRTC 和 ETC)的质量不够高,并且目标平台不完全支持 ASTC,请尝试采用 16 位纹理而不是 32 位纹理。
请参阅以下手册了解有关各平台的推荐纹理压缩格式的更多信息。
https://docs.unity3d.com/cn/current/Manual/class-TextureImporterOverride.html
调整网格导入设置
与纹理很像,如果导入时不小心,网格可能占用过多内存。要尽可能减少网格占用的内存,请执行以下操作 :
检查网格导入设置
检查多边形数量
分辨率越高的模型,需要的内存使用量越大,并且可能占用更长的 GPU 时间。您的背景几何体是否需要五十万个多边形?考虑减少所选 DCC 包中的模型。删除摄像机的视角看不到的多边形。使用纹理和法线贴图而不是高密度网格来实现精细的细节。
使用 AssetPostprocessor 自动执行导入设置
利用 AssetPostprocessor 可以在导入资源时运行脚本。这样,您可以在导入模型、纹理、音频等之前和 / 或之后对设置进行自定义。
AssetPostprocessor:
https://docs.unity3d.com/ScriptReference/AssetPostprocessor.html
使用可寻址资源系统
可寻址资源系统提高一种简化的方法来管理内容,按“地址”或别名加载资源包。这种统一的系统从本地路径或远程内容分发网络 (CDN) 执行异步加载。
可寻址资源系统:
http://docs.unity3d.com/Packages/com.unity.addressables@1.18/manual/index.html
如果将非代码资源(模型、纹理、预制件、音频,甚至整个场景)拆分为资源包,则可以将它们分为可下载内容 (DLC)。
资源包:
https://docs.unity3d.com/cn/current/Manual/AssetBundlesIntro.html
然后,使用 Addressables 为移动端应用程序创建较小的初始构建版本。云端资源分发可承载您的游戏内容并随着玩家的游戏进展将内容分发至玩家。
云端资源分发:
https://unity.cn/product/cloud-content-delivery
通过以下链接,查看可寻址资源系统如何简化资源管理。
https://unity.com/cn/how-to/simplify-your-content-management-addressables
图形和 GPU 优化
每一帧,Unity 都需要确定必须渲染哪些对象,然后创建绘制调用。绘制调用是调用图形 API 来绘制对象(如三角形),而批处理是要一起执行的一组绘制调用。
随着项目变得更加复杂,您需要用管线来优化 GPU 的工作负载。通用渲染管线 (URP) 目前使用单通道前向渲染器将高质量图形传输给移动平台(未来版本中将提供延迟渲染功能)。来自游戏主机和 PC 的、基于物理的光照和材质也可以缩放为适合手机或平板电脑。
以下指导原则可以帮助您提高图形处理速度。
批处理执行绘制调用
将要绘制的对象组合为批次,可以尽可能减少在批次中绘制每个对象所需的状态更改。这种方式通过减少渲染对象的 CPU 开销,可以改善性能。Unity 可以使用以下几种方法将多个对象组合为较少的批次 :
使用帧调试器 (Frame Debugger)
帧调试器介绍每一帧是如何通过各绘制调用构建的。这是非常重要的工具,可以解决着色器属性问题,帮助您分析游戏渲染方式。
长按关注
第一时间了解Unity引擎动向,学习最新开发技巧
点击“阅读原文”,跳转Unity中文课堂